#pragma comment(lib, "SDL.lib")
#pragma comment(lib, "SDLmain.lib")
#pragma comment(lib, "SDL_mixer.lib")
#pragma comment(lib, "SDL_image.lib")
#pragma comment(lib, "OpenGL32.lib")

#include "Globals.hpp"



#include "Entity.h"
#include "Button.h"
#include "Moving Entity.h"
#include "Entity Manager.h"
#include <string>
#include "ExecutionLog.h"
#include "SoundEngine.h"
#include "ClippingPlane.h"
#include "LoadingScreen.h"
#include <time.h>

#include "SuperData.h"

// States
#include "Gamescreen.h"
#include "GameState.h"
#include "MainMenu.h"
#include "Editor.h"
#include "MapSelector.h"

// Lua
#include "Lua.h"
#include "GenericKeys.h"
#include "Lua Functions.h"
#include "Lua UI Functions.h"

#include "GLFT_Font.hpp"
#include "GameWorld.h"


using namespace std;

void clean_up()
{

		//TextDisplay->Destroy();
		SoundPlay->CleanUp();
		Mix_CloseAudio();
		Entity::FreeAllImages();
		Key->Destroy();
		ExecuteLog->CloseFile();

		World->FreeMemory();
        //TextDisplay->Clear();

        NullDelete(currentState);

        SDL_Quit();

}

void change_state_working()
{
    //If the state needs to be changed
    if( currentState->nextState != STATE_NULL )
    {
                // If the state is deleted...
                int tempNextState = currentState->nextState;
        //Delete the current state
        if( currentState->nextState != STATE_EXIT )
        {
            NullDelete(currentState);
        }
        
        //Change the state
        switch( tempNextState )
        {     
            case STATE_MAINMENU:
                currentState = new MainMenu();
                break;

            case STATE_GAMEPLAY:
				currentState = new GameScreen();
				break;

			case STATE_EDITOR:
				currentState = new Editor();
				break;

			case STATE_MAP_SELECTOR:
				currentState = new MapSelector();
				break;


        }
        
        //Change the current state ID
        currentState->stateID = currentState->nextState;
        
        //NULL the next state ID
        currentState->nextState = STATE_NULL;    
    }
}

bool Initialize_OpenGL()
{
    //Set clear color
    glClearColor( 0, 0, 0, 1 );


    //Set projection
    glMatrixMode( GL_PROJECTION );
	glPushMatrix();
    glLoadIdentity();
    glOrtho( 0, DataLoader->WINDOW_WIDTH, DataLoader->WINDOW_HEIGHT, 0.0f, -1.0f, 2.0f );

    //Initialize modelview matrix
    glMatrixMode( GL_MODELVIEW );
	glPushMatrix();
    glLoadIdentity();

    //If there was any errors
    if( glGetError() != GL_NO_ERROR )
    {
        return false;
    }

	// TEXTURE CODE
	glEnable(GL_TEXTURE_2D);
	
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);


	glFrontFace(GL_CW);

	glEnable(GL_ALPHA_TEST);


	glEnable(GL_TEXTURE_ENV);
	

	// enable line smoothing
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

    //If everything initialized
    return true;
}

// Give values to a bunch of variables in Lua (NOTE: these tables need to be built first!)
void BuildLuaValues()
{
	Lua->RunString("menu_panels = {}");
	Lua->RunString("menu_panels.screen = 701");
	Lua->RunString("menu_panels.new_game = 702");
	Lua->RunString("menu_panels.editor = 703");
	Lua->RunString("menu_panels.exit = 704");
	Lua->RunString("menu_panels.map_selector = 705");

	Lua->RunString("game_panels = {}");
	Lua->RunString("game_panels.unit = 801");

	Lua->RunString("editor_panels = {}");
	Lua->RunString("editor_panels.tiles = 901");
	Lua->RunString("editor_panels.algorithmsBASE = 902");
	Lua->RunString("editor_panels.algorithms = {}");

	string str = "editor_panels.algorithms.SNAKE_FULL = ";
	str += GetString(SNAKE_FULL);
	Lua->RunString(str.c_str());

	str = "editor_panels.algorithms.SNAKE_FAST = ";
	str += GetString(SNAKE_FAST);
	Lua->RunString(str.c_str());

	str = "editor_panels.algorithms.CHISEL = ";
	str += GetString(CHISEL);
	Lua->RunString(str.c_str());

	str = "editor_panels.algorithms.SPARSE = ";
	str += GetString(SCATTER);
	Lua->RunString(str.c_str());

	str = "editor_panels.algorithms.BOX = ";
	str += GetString(BOX);
	Lua->RunString(str.c_str());

	str = "editor_panels.algorithms.FOCUS_POINT = ";
	str += GetString(FOCUS_POINT);
	Lua->RunString(str.c_str());

	Lua->RunString("editor_panels.buttons = 950");
	Lua->RunString("editor_panels.buttonIDs = {}");
	Lua->RunString("editor_panels.buttonIDs.displaySelection = 951");
	Lua->RunString("editor_panels.buttonIDs.buildRoom = 952");
	Lua->RunString("editor_panels.buttonIDs.buildPath = 953");
	Lua->RunString("editor_panels.buttonIDs.saveToLua = 954");
	Lua->RunString("editor_panels.buttonIDs.moveRooms = 955");
	Lua->RunString("editor_panels.buttonIDs.removeRoom = 956");


	Lua->RunString("map_selector_panels = {}");
	Lua->RunString("map_selector_panels.screen = 1001");
	Lua->RunString("map_selector_panels.close = 1002");
	Lua->RunString("map_selector_panels.notrec = 1003");

}

void Initialize()
{

	ExecuteLog->Init();
	DataLoader->LoadSettings("Settings.lua");
	//DataLoader->LoadData("map1Config.lua");

	srand(time(0));

	// SDL, TTF, and Music
	SDL_Init(SDL_INIT_EVERYTHING);	
	Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 4096);

	// create the icon
	SDL_Surface* icon = IMG_Load("../Project/Graphics/Loading/Icon.png");
	//assert(icon);
  if(icon == NULL)
    cout << IMG_GetError() << endl;
	SDL_WM_SetIcon(icon, NULL);
	SDL_FreeSurface(icon);

	// set caption
	SDL_WM_SetCaption("RTS", NULL);

	// are we in fullscreen?
	if(DataLoader->IsFullscreen())
	{
		const SDL_VideoInfo* window = SDL_GetVideoInfo();
		DataLoader->WINDOW_HEIGHT = window->current_h;
		DataLoader->WINDOW_WIDTH = window->current_w;
		SDL_SetVideoMode(DataLoader->WINDOW_WIDTH, DataLoader->WINDOW_HEIGHT, DataLoader->WINDOW_BPP, SDL_OPENGL | SDL_FULLSCREEN );
	}
	else
		SDL_SetVideoMode(DataLoader->WINDOW_WIDTH, DataLoader->WINDOW_HEIGHT, DataLoader->WINDOW_BPP, SDL_OPENGL );

		


	Initialize_OpenGL();
	ilInit();  // Initialize DevIL
	ilutRenderer(ILUT_OPENGL); // Initialize DevIL's openGL bindings etc
	Key->Init();
	//Entity::Init();
	InitLuaFunctions();
	InitLuaUIFunctions();
	BuildLuaValues(); // gives values to a bunch of variables in lua
	Lua->RunScript("Scripts/Globals.lua");

	Entity::Init();
	Entity::AddAllImages();
	//TextDisplay->Init();

	//LoadingScreen loadScreen("g_Menu_Background");   

	// Give Lua some handy functions
	//loadScreen.SetProgress(.10);
	//loadScreen.SetBottomText("Loading Lua Functions...");
	//loadScreen.Render();
	
	// Creates the user interface
	//loadScreen.SetProgress(.20);
	//loadScreen.SetBottomText("Creating the User Interface...");
	//loadScreen.Render();
	Lua->RunScript("Scripts/UI/CreateAll.lua");

	// Adds the maps
	//loadScreen.SetProgress(.30);
	//loadScreen.SetBottomText("Adding maps to the engine...");
	//loadScreen.Render();
	Lua->RunScript("Scripts/Maps.lua");
		
	// Music
	//loadScreen.SetProgress(.40);
	//loadScreen.SetBottomText("Loading Sounds...");
	//loadScreen.Render();

	SoundPlay->Init();
	SoundPlay->Play(DataLoader->GetMusicName());
	Mix_VolumeMusic(DataLoader->GetSoundVolume());

	ExecuteLog->AddMessage("--SDL & OpenGL fully initialized (includes all additional libraries)--");


	//loadScreen.SetProgress(.70);
	//loadScreen.SetBottomText("Creating the menu state");
	//loadScreen.Render();


	//Set the current game state object
	currentState = new MainMenu();

    //Set the current state ID
	currentState->stateID = STATE_MAINMENU;
    currentState->nextState = STATE_NULL;

}

#include "MapGenerator.h"





#include "Timer.hpp"

extern "C" int main( int argc, char* argv[] )
{
	//Delete(SparseGraph<NavGraphNode<void*>, GraphEdge>::GetGraph(100, 100));
	Initialize();
	// Turn off the cursor
	//SDL_ShowCursor(0);
	//UIElement cursor;
	//cursor.SetImageID("c_Normal");
	//int x, y;

	float t = 0.0f;
	const int updateFPS = 30;
	const float dt = (1000.0f / updateFPS); // one update per frame @ 30 fps

	float currentTime = SDL_GetTicks();
	float accumulator = 0.0f;
	Timer updateTimer;

	//ClientCommunicator client;
	//client.Connect();

	//While the user hasn't quit
    while(currentState->stateID != STATE_EXIT)
    {   
		accumulator += updateTimer.GetElapsedMilliseconds();
		updateTimer.Restart();

        //Do state event handling
        currentState->handle_events();
        
        //Do state logic
		while(accumulator >= dt)
		{
			currentState->logic();
			accumulator -= dt;

			if(accumulator > dt * 10) // if we are 10 frames behind, then update
			{
				accumulator = 0;
				Log->AddMessage("reseting accumulator", red);
				//Log->AddMessage("resycing from server", red);
				//client.Resync();
			}
		}

		//while(client.RecieveUpdates()) {}
		
		//if(client.GetChatlogMessages().size() != 0)
			//currentState->add_chat_messages(client.GetChatlogMessages());

        //Change state if needed
        change_state_working();
        
       

		
		//SDL_GetMouseState(&x, &y);
		//cursor.ChangeX(x + ClipPlane->GetX());
		//cursor.ChangeY(y + ClipPlane->GetY());
		//cursor.applySurface();


		// Check to see if the music needs to be changed (to prevent looping)
		SoundPlay->Update();

		 //Do state rendering & clear the screen
        currentState->render();

        //Update screen
	    SDL_GL_SwapBuffers();

		// Clear the screen
		glClear(GL_COLOR_BUFFER_BIT);

    }


    clean_up();
    return 0;

}
